package com.uni.crawl.service.impl.crawl;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.yulichang.base.MPJBaseServiceImpl;
import com.github.yulichang.toolkit.MPJWrappers;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.uni.crawl.common.enums.crawl.CrawlInstanceStatusEnum;
import com.uni.crawl.mapper.CrawlInstanceMapper;
import com.uni.crawl.model.entity.crawl.CrawlInstance;
import com.uni.crawl.model.entity.crawl.CrawlNamespace;
import com.uni.crawl.model.entity.crawl.CrawlTemplate;
import com.uni.crawl.model.query.crawl.CrawlInstancePageQuery;
import com.uni.crawl.model.vo.crawl.CrawlInstanceVO;
import com.uni.crawl.service.PageQueryUtils;
import com.uni.crawl.service.crawl.CrawlInstanceService;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;

/**
 * <p>
 * 爬虫实例 服务实现类
 * </p>
 *
 * @author JervisPG
 * @since 2023-12-16
 */
@Service
public class CrawlInstanceServiceImpl extends MPJBaseServiceImpl<CrawlInstanceMapper, CrawlInstance> implements CrawlInstanceService {

    @Override
    public Page<CrawlInstanceVO> getPage(CrawlInstancePageQuery pageQuery) {
        String nsCode = pageQuery.getNsCode();
        String tmplCode = pageQuery.getTmplCode();

        MPJLambdaWrapper<CrawlInstance> wp = MPJWrappers.lambdaJoin();
        wp.selectAll(CrawlInstance.class);
        wp.select(CrawlNamespace::getNsName);
        wp.select(CrawlTemplate::getTmplName);

        wp.leftJoin(CrawlNamespace.class, CrawlNamespace::getNsCode, CrawlInstance::getNsCode);
        wp.leftJoin(CrawlTemplate.class, CrawlTemplate::getTmplCode, CrawlInstance::getTmplCode);

        wp.eq(Objects.nonNull(pageQuery.getId()), CrawlInstance::getId, pageQuery.getId());
        wp.eq(StrUtil.isNotEmpty(nsCode), CrawlInstance::getNsCode, nsCode);
        wp.like(StrUtil.isNotEmpty(tmplCode), CrawlInstance::getTmplCode, tmplCode);
        wp.eq(Objects.nonNull(pageQuery.getInstanceStatus()), CrawlInstance::getInstanceStatus, pageQuery.getInstanceStatus());
        PageQueryUtils.wrapTimeRange(wp, CrawlInstance::getCreateTime, pageQuery);

        wp.orderByDesc(CrawlInstance::getId);

        return selectJoinListPage(PageQueryUtils.getPage(pageQuery), CrawlInstanceVO.class, wp);
    }

    @Override
    public void setInstanceStatus(Long id, CrawlInstanceStatusEnum statusEnum) {
        LambdaUpdateWrapper<CrawlInstance> wp = Wrappers.lambdaUpdate();
        wp.eq(CrawlInstance::getId, id);

        wp.set(CrawlInstance::getInstanceStatus, statusEnum.getStatus());
        wp.set(CrawlInstance::getUpdateTime, LocalDateTime.now());
        if (CrawlInstanceStatusEnum.PROCESSING == statusEnum) {
            wp.set(CrawlInstance::getStartTime, LocalDateTime.now());
        } else if (CrawlInstanceStatusEnum.SUCCESS == statusEnum) {
            wp.set(CrawlInstance::getEndTime, LocalDateTime.now());
        }

        update(wp);
    }

    @Override
    public List<CrawlInstance> list(CrawlInstanceStatusEnum statusEnum) {
        LambdaUpdateWrapper<CrawlInstance> wp = Wrappers.lambdaUpdate();
        wp.eq(CrawlInstance::getInstanceStatus, statusEnum.getStatus());
        return list(wp);
    }

    @Override
    public void increaseTotal(Long id, int count) {
        LambdaUpdateWrapper<CrawlInstance> wp = Wrappers.lambdaUpdate();
        wp.eq(CrawlInstance::getId, id);
        wp.setSql(String.format("queue_total = queue_total + %d", count));
        update(wp);
    }

    @Override
    public void increaseFinish(Long id, int count) {
        LambdaUpdateWrapper<CrawlInstance> wp = Wrappers.lambdaUpdate();
        wp.eq(CrawlInstance::getId, id);
        wp.setSql(String.format("queue_finish = queue_finish + %d", count));
        update(wp);
    }

    @Override
    public void calculateStatus(Long id) {
        CrawlInstance ins = getById(id);
        if (Objects.equals(ins.getQueueTotal(), ins.getQueueFinish())) {
            ins.setInstanceStatus(CrawlInstanceStatusEnum.SUCCESS.getStatus());
            ins.setEndTime(LocalDateTime.now());
            updateById(ins);
        }
    }
}
